//
//  GPThreadManger.m
//  StudyDemo01
//
//  Created by 心晨 on 2024/5/9.
//

// 是否开辟线程与队列无关，只跟异步有关

#import "GPThreadManger.h"
#import "YYDispatchQueuePool.h"

@implementation GPThreadManger

- (instancetype)init
{
    self = [super init];
    if (self) {
        
    }
    return self;
}

+ (instancetype)shareInstance {
    
    static GPThreadManger *manager = nil;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[GPThreadManger alloc] init];
    });
    
    return manager;
}

- (void)dispatchQueuePool {
    // 里面是根据 queueCount 的创建对应数量的 串行队列，执行任务时 轮着返回 队列
    // 这里其实涉及到 类似于 dispatch_apply的作用，但他是根据系统CPU核心数动态调整并发数量
    YYDispatchQueuePool *pool = [[YYDispatchQueuePool alloc] initWithName:@"file.read" queueCount:5 qos:NSQualityOfServiceBackground];
    for (int i = 0; i < 100000; i++) {
        dispatch_queue_t queue = [pool queue];
        dispatch_async(queue, ^{
            NSLog(@"YYDispatchQueuePool queue %d Thread: %@ ", i, [NSThread currentThread]);
        });
    }
}

- (void)dispatchQueuePriority {
    YYDispatchQueuePool *pool = [[YYDispatchQueuePool alloc] initWithName:@"file.read" queueCount:1 qos:NSQualityOfServiceBackground];
    dispatch_queue_t queue = [pool queue];
    YYDispatchQueuePool *poolB = [[YYDispatchQueuePool alloc] initWithName:@"file.read" queueCount:1 qos:NSQualityOfServiceUserInitiated];
    dispatch_queue_t queueB = [poolB queue];
    
    dispatch_async(queue, ^{
        NSLog(@"YYDispatchQueuePool queue Thread: %@ ", [NSThread currentThread]);
    });
    
    dispatch_async(queueB, ^{
        NSLog(@"YYDispatchQueuePool queueB Thread: %@ ", [NSThread currentThread]);
    });
        
}


/// 串行队列 异步会开线程， 任务不一定都在一个线程内执行
- (void)serialQueue {
    
    dispatch_queue_t serialQueue = dispatch_queue_create("com.demo.serialQueue", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(serialQueue, ^{
        NSLog(@" ====== serialQueue 1 %@", [NSThread currentThread]);
    });

    dispatch_async(serialQueue, ^{
        NSLog(@" ====== serialQueue 2 %@", [NSThread currentThread]);
    });

    dispatch_async(serialQueue, ^{
        NSLog(@" ====== serialQueue 3 %@", [NSThread currentThread]);
    });
    
}

- (void)concurrentQueue {
    
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.demo.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(concurrentQueue, ^{
        NSLog(@" ====== concurrentQueue 1 %@", [NSThread currentThread]);
    });

    dispatch_async(concurrentQueue, ^{
        NSLog(@" ====== concurrentQueue 2 %@", [NSThread currentThread]);
    });

    dispatch_async(concurrentQueue, ^{
        NSLog(@" ====== concurrentQueue 3 %@", [NSThread currentThread]);
    });
    
}

- (void)dispatchGroup {
    
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        sleep(2);
        NSLog(@" ====== dispatchGroup 1 %@", [NSThread currentThread]);
    });
    
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        sleep(1);
        NSLog(@" ====== dispatchGroup 2 %@", [NSThread currentThread]);
    });
    
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@" ====== dispatchGroup 3 %@", [NSThread currentThread]);
    });
    
    // dispatch_group_wait 阻塞线程，死等，等group任务完后再执行
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@" ====== dispatchGroup 4 %@", [NSThread currentThread]);
        
}

- (void)dispatchGroupNotify {
    
    // dispatch_group_enter 、 dispatch_group_leave enter多少次就得leave多少次
    
    dispatch_queue_t concurrentQueue1 = dispatch_queue_create("com.demo.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t concurrentQueue2 = dispatch_queue_create("com.demo.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t concurrentQueue3 = dispatch_queue_create("com.demo.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_enter(group);
    dispatch_group_async(group, concurrentQueue1, ^{
        sleep(3);
        NSLog(@" ====== dispatchGroupNotify 1 %@", [NSThread currentThread]);
        dispatch_group_leave(group);
    });
    
    dispatch_group_enter(group);
    dispatch_group_async(group, concurrentQueue2, ^{
        NSLog(@" ====== dispatchGroupNotify 2 %@", [NSThread currentThread]);
        dispatch_group_leave(group);
    });
    
    dispatch_group_enter(group);
    dispatch_group_async(group, concurrentQueue3, ^{
        sleep(2.5);
        NSLog(@" ====== dispatchGroupNotify 3 %@", [NSThread currentThread]);
        dispatch_group_leave(group);
    });
    
    // dispatch_group_notify 不会阻塞线程，等group任务完后再执行
    dispatch_group_notify(group, concurrentQueue2, ^{
        NSLog(@" ====== dispatchGroupNotify 5 %@", [NSThread currentThread]);
    });
    
    
}

- (void)dispatchBarrierAsync {
    
    // 栅栏函数不能在全局队列中使用，原因：
    // 全局队列是系统创建，系统程序共享的，如果栅栏函数生效会导致其他程序的执行出现异常
    // dispatch_barrier_async 异步提交任务，可能会开辟线程
    // dispatch_barrier_sync 同步提交任务，不会开辟线程
    
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(concurrentQueue, ^{
        NSLog(@" ====== dispatchBarrierAsync 1 %@", [NSThread currentThread]);
    });

    dispatch_async(concurrentQueue, ^{
        NSLog(@" ====== dispatchBarrierAsync 2 %@", [NSThread currentThread]);
    });
    
    dispatch_barrier_async(concurrentQueue, ^{
        // 在栅栏处执行的任务，会在前面的任务完成后执行，且会阻塞后续任务的执行
        // 可以在这里执行对共享资源的读写操作等
        sleep(2.5);
        NSLog(@" ====== dispatchBarrierAsync 3 %@", [NSThread currentThread]);
    });

    dispatch_async(concurrentQueue, ^{
        NSLog(@" ====== dispatchBarrierAsync 4 %@", [NSThread currentThread]);
    });

    dispatch_async(concurrentQueue, ^{
        NSLog(@" ====== dispatchBarrierAsync 5 %@", [NSThread currentThread]);
    });

}

@end
